package com.bb.flow.parser.impl.parsejson.parsenode;

import com.alibaba.fastjson2.JSONObject;
import com.bb.flow.api.exception.ParseException;
import com.bb.flow.config.AbstractConfigNode;
import com.bb.flow.config.enumtype.NodeType;
import com.bb.flow.parser.impl.parsejson.parsenode.nodeimp.ParseContainerNode;
import com.bb.flow.parser.impl.parsejson.parsenode.nodeimp.ParseFunctionNode;
import com.bb.flow.parser.impl.parsejson.parsenode.nodeimp.ParseJudgeNode;
import com.bb.flow.parser.impl.parsejson.parsenode.nodeimp.ParseSubFlowNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @author bigbeard
 * 流程节点解析调度器
 */
public class ParseNodeDispatcher {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 解析器缓存
     */
    private final Map<NodeType, IParseNode> parseNodeMap = new HashMap<>(4);
    /**
     * 类解析器
     */
    private ParseClassInfo parseClassInfo;
    /**
     * 节点基本信息解析器
     */
    private ParseNodeBaseInfo parseNodeBaseInfo;
    /**
     * 条件解析器
     */
    private ParseCondition parseCondition;


    /**
     * 构造函数
     *
     * @param parseClassInfo    类解析器
     * @param parseNodeBaseInfo 节点基本信息解析器
     * @param parseCondition    条件解析器
     */
    public ParseNodeDispatcher(ParseClassInfo parseClassInfo,
                               ParseNodeBaseInfo parseNodeBaseInfo,
                               ParseCondition parseCondition) {
        this.parseClassInfo = parseClassInfo;
        this.parseNodeBaseInfo = parseNodeBaseInfo;
        this.parseCondition = parseCondition;
    }

    public ParseNodeDispatcher() {
    }

    /**
     * 初始化调度器,调用此方法前需要设置好各种解析器
     */
    public void init() {
        ParseFunctionNode parseFunctionNode = new ParseFunctionNode();
        parseFunctionNode.setParseClassInfo(parseClassInfo);
        parseFunctionNode.setParseNodeBaseInfo(parseNodeBaseInfo);
        parseNodeMap.put(NodeType.FUNCTION_NODE, parseFunctionNode);

        ParseJudgeNode parseJudgeNode = new ParseJudgeNode();
        parseJudgeNode.setParseClassInfo(parseClassInfo);
        parseJudgeNode.setParseNodeBaseInfo(parseNodeBaseInfo);
        parseNodeMap.put(NodeType.JUDGE_NODE, parseJudgeNode);


        ParseContainerNode parseContainerNode = new ParseContainerNode();
        parseContainerNode.setParseClassInfo(parseClassInfo);
        parseContainerNode.setParseNodeBaseInfo(parseNodeBaseInfo);
        parseJudgeNode.setParseCondition(parseCondition);
        parseContainerNode.setNodeDispatcher(this);
        parseNodeMap.put(NodeType.CONTAINER_NODE, parseContainerNode);

        ParseSubFlowNode parseSubFlowNode = new ParseSubFlowNode();
        parseSubFlowNode.setParseClassInfo(parseClassInfo);
        parseSubFlowNode.setParseNodeBaseInfo(parseNodeBaseInfo);
        parseNodeMap.put(NodeType.SUBFLOW_NODE, parseSubFlowNode);
    }

    /**
     * 设置节点基本信息解析器
     *
     * @param parseNodeBaseInfo 解析器
     */
    public void setParseNodeBaseInfo(ParseNodeBaseInfo parseNodeBaseInfo) {
        this.parseNodeBaseInfo = parseNodeBaseInfo;
    }

    /**
     * 设置类解析器
     *
     * @param parseClassInfo 解析器
     */
    public void setParseClassInfo(ParseClassInfo parseClassInfo) {
        this.parseClassInfo = parseClassInfo;
    }

    /**
     * 节点解析调度器
     *
     * @param jsonObject       节点配置json对象
     * @param flowTemplateName 流程模版名称
     * @return 节点对象
     */
    public AbstractConfigNode dispatcherParseNode(JSONObject jsonObject, String flowTemplateName) throws ParseException {
        return dispatcherParseNode(jsonObject, "", flowTemplateName);
    }

    /**
     * 节点解析调度器
     *
     * @param jsonObject       节点配置json对象
     * @param nodeName         节点名称
     * @param flowTemplateName 流程模版名称
     * @return 节点对象
     */
    public AbstractConfigNode dispatcherParseNode(JSONObject jsonObject, String nodeName, String flowTemplateName) throws ParseException {
        NodeType nodeType = parseNodeBaseInfo.getNodeType(jsonObject.getString("NodeType"), flowTemplateName);
        if (nodeType == null) {
            return null;
        }
        if (parseNodeMap.containsKey(nodeType)) {
            return parseNodeMap.get(nodeType).parse(jsonObject, flowTemplateName, nodeName);
        }

        return null;
    }

    /**
     * 设置条件解析器
     *
     * @param parseCondition 条件解析器
     */
    public void setParseCondition(ParseCondition parseCondition) {
        this.parseCondition = parseCondition;
    }
}


